package cz.mff.curreco.utils;

import java.awt.image.BufferedImage;
import java.awt.image.ImageProducer;
import java.awt.image.PixelGrabber;
import java.awt.image.WritableRaster;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.awt.AlphaComposite;
import java.awt.Graphics2D;
import java.awt.RenderingHints;

import javax.imageio.ImageIO;

import com.sun.media.jai.util.ImageUtil;

/**
 * Service for Converting InputStream into bitmap.
 */
public class Convert {
	
	/**
	 * <pre> Method returns instance of bitmat created from InputStream</pre>
	 * @param input source of bitmap
	 * @return instance of bitmap created from stream, null if error occurs.
	 */
	public static BufferedImage streamToImage(InputStream input)
	{
		return streamToImage(input,true);
	}

	/**
	 * <pre>Method returns instance of bitmap created from InputStream.</pre>
	 * @param input input source of image
	 * @param resize If true, resize image under dimension 600x600.
	 * @see streamToImage(InputStream input)
	 */
	public static BufferedImage streamToImage(InputStream input, Boolean resize)
	{
		BufferedImage im ;
		try {
			im=ImageIO.read(input);
		} catch (IOException e) {
			e.printStackTrace();
			return null;
		}
		if (resize)
			return ResizeImage(im);
		else
			return im;
	}
	
	/**
	 * <pre>Funcition resizes image until it's dimensions are smaller than 600x600 pixels</pre> 
	 * @param image input image
	 * @param resized image
	 */
	public static BufferedImage ResizeImage(BufferedImage image)
	{
		int width = image.getWidth();
		int height = image.getHeight();
		if (width<=600 && height<=600)
			return image;
		while (width > 600 && height>600)
		{
			width >>=1;
			height>>=1;
		}

		int type = image.getType() == 0? BufferedImage.TYPE_INT_ARGB : image.getType();
		BufferedImage resizedImage = new BufferedImage(width, height, type);
		Graphics2D g = resizedImage.createGraphics();
		g.setComposite(AlphaComposite.Src);
		g.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
		RenderingHints.VALUE_INTERPOLATION_BILINEAR);
		g.setRenderingHint(RenderingHints.KEY_RENDERING,
		RenderingHints.VALUE_RENDER_QUALITY);
		g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
		RenderingHints.VALUE_ANTIALIAS_ON);
		g.drawImage(image, 0, 0, width, height, null);
		g.dispose();
		return resizedImage;
	}
	
	/**
	 * 
	 * @param im Instance of bitmap
	 * @return string, that contains width, height of image and color of pixel in center.
	 */
	public static String getImageInfo(BufferedImage im)
	{
		if (im == null) 
			return "";
		// get width and height
		int width= im.getWidth();
		int height = im.getHeight();
		StringBuilder sb = new StringBuilder();
		sb.append("width/Height: ").append(width).append("/").append(height).append(" ");
		
		// get center of picture
		width >>=1;
		height>>=1;
		
		// get color
		// "& 0xFFFFFF" is for getting only RGB
		// it removes value of pixel transparency
		int color= im.getRGB(width, height) & 0xFFFFFF;
		sb.append("center color: ").append(Integer.toString(color,16));
		
		return sb.toString();
		
	}
	
	public static InputStream imageToStream(BufferedImage bi) {
		ByteArrayOutputStream os = new ByteArrayOutputStream();
		try {
			ImageIO.write(bi, "png", os);
		} catch (IOException e) {
			System.out.println(e);
		}
		InputStream is = new ByteArrayInputStream(os.toByteArray());
		return is;
	}
	
	public static byte[] imageToByteArray(BufferedImage bi) throws IOException {
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		ImageIO.write( bi, "jpg", baos );
		baos.flush();
		byte[] imageInByte = baos.toByteArray();
		baos.close();
		return imageInByte;
	}
	
	public static BufferedImage byteArrayToImage(byte[] byteArray) throws IOException {
		InputStream in = new ByteArrayInputStream(byteArray);
		BufferedImage bi = ImageIO.read(in);
		return bi;
	}
	
	public static int[] imageToIntArray(BufferedImage bi) {
		int width = bi.getWidth();
		int height = bi.getHeight();
		int[] image = new int[width*height];
		PixelGrabber pg = new PixelGrabber(bi, 0, 0, width, height, image, 0, width);
		try { 
			pg.grabPixels(); 
		} catch(InterruptedException e) {
			System.out.println(e.getStackTrace());
		}
		return image;
	}
	
	public static BufferedImage intArrayToImage(int[] intArray, int width, int height) {
		BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
	    image.setRGB(0, 0, width, height, intArray, 0, width);
		return image;
	}
}
